package com.hyr.spring_axon.account;

import com.hyr.spring_axon.account.command.AccountCreateCommand;
import com.hyr.spring_axon.account.command.AccountDepositCommand;
import com.hyr.spring_axon.account.command.AccountWithdrawCommand;
import com.hyr.spring_axon.account.event.AccountCreatedEvent;
import com.hyr.spring_axon.account.event.AccountDepositedEvent;
import com.hyr.spring_axon.account.event.AccountWithdrawedEvent;
import org.axonframework.commandhandling.CommandHandler;
import org.axonframework.eventsourcing.EventSourcingHandler;
import org.axonframework.spring.stereotype.Aggregate;

import javax.persistence.Entity;
import javax.persistence.Id;

import static org.axonframework.modelling.command.AggregateLifecycle.apply;

@Aggregate
@Entity(name = "tb_account")
public class Account {

    @Id
    private String accountId;

    private Double deposit;

    public Account() {
    }

    @CommandHandler
    public Account(AccountCreateCommand command) {
        apply(new AccountCreatedEvent(command.getAccountId()));
    }

    @CommandHandler
    public void handle(AccountDepositCommand command){
        apply(new AccountDepositedEvent(command.getAccountId(),command.getAmount()));
    }

    @CommandHandler
    public void handle(AccountWithdrawCommand command) throws IllegalAccessException {
        if (this.deposit >= command.getAmount()){
            apply(new AccountWithdrawedEvent(command.getAccountId(),command.getAmount()));
        }else {
            throw new IllegalAccessException("余额不足");
        }
    }

    @EventSourcingHandler
    public void on(AccountCreatedEvent event){
        this.accountId = event.getAccountId();
        this.deposit =  0d;
    }

    @EventSourcingHandler
    public void on(AccountDepositedEvent event){
        this.deposit +=  event.getAmount();
    }

    @EventSourcingHandler
    public void on(AccountWithdrawedEvent event){
        this.deposit -=  event.getAmount();
    }


    public String getAccountId() {
        return accountId;
    }

    public void setAccountId(String accountId) {
        this.accountId = accountId;
    }

    public Double getDeposit() {
        return deposit;
    }

    public void setDeposit(Double deposit) {
        this.deposit = deposit;
    }
}
